/**
 * 
 */
package travibot.connection;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.Hashtable;

import travibot.connection.cookies.CookieHolder;
import travibot.connection.cookies.ICookieHolder;
import travibot.resource.ResourceHelper;


/**
 * @author tajzivit
 *
 */
public abstract class ConnectionFactory {

    private static final String FACTORY_KEY = "factory.connection";
    private static final String FACTORY_BUNDLE = "connection_factory";
    
    private static String activeFactoryKey = null;
    private static Hashtable<String, ConnectionFactory> pool = new Hashtable<String, ConnectionFactory>();
    
    private ICookieHolder cookieHolder = new CookieHolder();
    private boolean useCookies = false;
    private String protocol = "HTTP";
    private String requestMethod = "GET";
    
    public void setUseCookies(boolean useCookies){
        
        this.useCookies = useCookies;
        
        if(this.useCookies)
           setCookieHandler();
    }
    
    public boolean useCookies(){
        
        return this.useCookies;
    }
    
    public void setProtocol(String protocol){
        
        this.protocol = protocol;
    }
    
    public String getProtocol(){
        
        return this.protocol;
    }
    
    public String getRequestMethod() {
    
        return requestMethod;
    }

    public void setRequestMethod(String requestMethod) {
    
        this.requestMethod = requestMethod;
    }

    /**
     * if the factory with given key doesn't exists, new instance is created and stored in pool.
     * 
     * Then is the key stored as active factory. Active factory can be getted by getFactory() method.
     * 
     * @param key 
     * @return
     */
    public static ConnectionFactory getFactory(String key){
        
        if(null == key)
            throw new IllegalArgumentException("Argument key is null");
        
        ConnectionFactory factory = pool.get(key);
        activeFactoryKey = key;
        
        if(factory == null){
            try{
                
                Class clazz = Class.forName(ResourceHelper.getKeyValue(FACTORY_BUNDLE, FACTORY_KEY));
                
                factory = (ConnectionFactory)clazz.newInstance();
                
                pool.put(key, factory);
            }
            catch(Exception e){
                System.out.println(e.getMessage());
            }
        }
        
        return factory;
    }
    
    public static ConnectionFactory getFactory(){
        
        if(null == activeFactoryKey)
            throw new IllegalArgumentException("Argument key is null");
            
        return getFactory(activeFactoryKey);
    }
    
    /**
     * returns cookies holder
     * @return
     */
    public ICookieHolder getCookieHolder(){
        
        return this.cookieHolder;
    }
    
    /**
     * sets base url eg. s1.travian.cz
     * @param baseURL
     */
    public abstract void setBaseURL(String baseURL);
    
    /**
     * get returned stream from server according to given url
     * @param url
     * @return
     */
    public abstract InputStream getInputStream(String url);
    
    /**
     * converts returned stream to string
     * @param url
     * @return converted stream as string
     */
    public abstract String getInputStreamAsString(String url);
    
    /**
     * gets stream for writing to server
     * @param url
     * @return
     */
    public abstract OutputStream getOutputStream(String url);
    
    /**
     * adds attributes which has be sent to server
     * @param key
     * @param value
     */
    public abstract void addArgument(String key, String value);

    /**
     * gets arguments, write them to output stream and send to server
     * @param url
     */
    public abstract void send(String url);
    
    /**
     * opens connection
     *
     */
    public abstract void open();
    
    /**
     * close connection
     *
     */
    public abstract void close();
    
    /**
     * connect to given url
     * @param url
     */
    public abstract void connect(String url);
    
    /**
     * sets cookie handler which is used if cookies are enabled
     *
     */
    protected abstract void setCookieHandler();
}
